#include "stdafx.h"
#include "net/MediaType.hpp"
#include "net/MessageHeader.hpp"
#include "charset/ascii.hpp"
#include "charset/string.hpp"
using namespace JHCPP::charset;

NET_NAMESPACE_BEGIN

CMediaType::CMediaType(const std::string& mediaType)
{
	parse(mediaType);
}

CMediaType::CMediaType(const std::string& type, const std::string& subType) : m_type(type), m_subType(subType)
{
}

CMediaType::CMediaType(const CMediaType& mediaType)
	: m_type(mediaType.m_type),
	m_subType(mediaType.m_subType),
	m_parameters(mediaType.m_parameters)
{
}

CMediaType::~CMediaType()
{
}

CMediaType& CMediaType::operator = (const CMediaType& mediaType)
{
	if (&mediaType != this)
	{
		m_type       = mediaType.m_type;
		m_subType    = mediaType.m_subType;
		m_parameters = mediaType.m_parameters;
	}
	return *this;
}

CMediaType& CMediaType::operator = (const std::string& mediaType)
{
	parse(mediaType);
	return *this;
}

void CMediaType::swap(CMediaType& mediaType)
{
	std::swap(m_type, mediaType.m_type);
	std::swap(m_subType, mediaType.m_subType);
	m_parameters.swap(mediaType.m_parameters);
}

void CMediaType::setType(const std::string& type)
{
	m_type = type;
}

void CMediaType::setSubType(const std::string& subType)
{
	m_subType = subType;
}

void CMediaType::setParameter(const std::string& name, const std::string& value)
{
	m_parameters.set(name, value);
}

const std::string& CMediaType::getParameter(const std::string& name) const
{
	return m_parameters.get(name);
}

bool CMediaType::hasParameter(const std::string& name) const
{
	return m_parameters.has(name);
}

void CMediaType::removeParameter(const std::string& name)
{
	m_parameters.erase(name);
}

std::string CMediaType::toString() const
{
	std::string result;
	result.append(m_type);
	result.append("/");
	result.append(m_subType);
	for (CNameValueCollection::ConstIterator it = m_parameters.begin(); it != m_parameters.end(); ++it)
	{
		result.append("; ");
		result.append(it->first);
		result.append("=");
		CMessageHeader::quote(it->second, result);
	}
	return result;
}

bool CMediaType::matches(const CMediaType& mediaType) const
{
	return matches(mediaType.m_type, mediaType.m_subType);
}

bool CMediaType::matches(const std::string& type, const std::string& subType) const
{
	return icompare(m_type, type) == 0 && icompare(m_subType, subType) == 0;
}

bool CMediaType::matches(const std::string& type) const
{
	return icompare(m_type, type) == 0;
}

bool CMediaType::matchesRange(const CMediaType& mediaType) const
{
	return matchesRange(mediaType.m_type, mediaType.m_subType);
}

bool CMediaType::matchesRange(const std::string& type, const std::string& subType) const
{
	if (m_type == "*" || type == "*" || icompare(m_type, type) == 0) 
	{
		return m_subType == "*" || subType == "*" || icompare(m_subType, subType) == 0;
	}
	else 
		return false;
}

bool CMediaType::matchesRange(const std::string& type) const
{
	return m_type == "*" || type == "*" || matches(type);
}

void CMediaType::parse(const std::string& mediaType)
{
	m_type.clear();
	m_subType.clear();
	m_parameters.clear();
	std::string::const_iterator it  = mediaType.begin();
	std::string::const_iterator end = mediaType.end();
	while (it != end && CAscii::isSpace(*it)) ++it;
	while (it != end && *it != '/') m_type += *it++;
	if (it != end) ++it;
	while (it != end && *it != ';' && !CAscii::isSpace(*it)) m_subType += *it++;
	while (it != end && *it != ';') ++it;
	CMessageHeader::splitParameters(it, end, m_parameters);
}


NET_NAMESPACE_END
